#if !defined(__CLIENT_VERSION_MANAGER_H)
#define __CLIENT_PROFILE_MANAGER_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


#include "Util.h"

#include "CriticalSection.h"
#include "Singleton.h"
#include "TimerManager.h"
#include "HttpConnection.h"
#include "SettingsManager.h"

class VersionManagerListener {
public:
	typedef VersionManagerListener* Ptr;
	typedef vector<Ptr> List;
	typedef List::iterator Iter;
	enum Types {
		MAKE_NEW_CONNECTION,
		LIST_UPDATED,
		CLIENT_UPDATED,
		ADD_LINE

	};
	
	virtual void on(Types) throw() { };
	virtual void on(Types, const string&) throw() { };
	virtual void on(Types, const string&, const string&, const string&, const string&) throw() { };
};

class ClientVersion {
	public:
	typedef vector<ClientVersion> List;
	typedef List::iterator Iter;

	ClientVersion() : id(0), alert(0) { };

	ClientVersion(int aId, const string& aClientName, const string& aLastVersion, const string& aCurrentVersion, 
		const string& aComment, const string& aAddress, const string& aClientAddress, const string& aUpdateTime, int aAlert, int aUpdated) 
		throw() : 
	id(aId), clientName(aClientName), lastVersion(aLastVersion), currentVersion(aCurrentVersion), comment(aComment), 
		address(aAddress), clientAddress(aClientAddress), updateTime(aUpdateTime), alert(aAlert), updated(aUpdated)
	{ };

	ClientVersion(const ClientVersion& rhs) : id(rhs.id), clientName(rhs.clientName), lastVersion(rhs.lastVersion), currentVersion(rhs.currentVersion), 
		comment(rhs.comment), address(rhs.address), clientAddress(rhs.clientAddress), updateTime(rhs.updateTime), alert(rhs.alert), updated(rhs.updated)
	{

	}

	ClientVersion& operator=(const ClientVersion& rhs) { 
		id = rhs.id;
		clientName = rhs.clientName;
		lastVersion = rhs.lastVersion;
		currentVersion = rhs.currentVersion;
		comment = rhs.comment;
		address = rhs.address;
		clientAddress = rhs.clientAddress;
		updateTime = rhs.updateTime;
		alert = rhs.alert;
		updated = rhs.updated;
		return *this;
	}

		GETSET(int, id, Id);
		GETSET(string, clientName, ClientName);
		GETSET(string, lastVersion, LastVersion);
		GETSET(string, currentVersion, CurrentVersion);
		GETSET(string, comment, Comment);
		GETSET(string, address, Address);
		GETSET(string, clientAddress, ClientAddress);
		GETSET(string, updateTime, UpdateTime);
		GETSET(int, alert, Alert);
		GETSET(int, updated, Updated);

};
class ClientVersionManager : public Singleton<ClientVersionManager>, public Speaker<VersionManagerListener>
	, TimerManagerListener, private HttpConnectionListener, private VersionManagerListener
{
public:
	void setVersion(const string& aVersion, const string& aMessage, const string& aURL, const string& aLine, const string& aVersion2, const string& aVersion3);
	// pothead starts svn191
	string getThisString(string input, string startText, string endText, int startSize);
	// pothead ends

	ClientVersion::List& getClientVersions(bool httpUpdate = false) {
		Lock l(cs);
		//Sulan start svn5?
		if(httpUpdate){
			clientVersions.clear();
			loadClientList();
		}
		//End
		return clientVersions;
	}
	

	ClientVersion addClientVersion(
		const string& clientName, 
		const string& lastVersion, 
		const string& currentVersion, 
		const string& comment, 
		const string& address, 
		const string& clientAddress, 
		const string& updateTime, 
		int alert,
		int updated
		) {
		Lock l(cs);
		clientVersions.push_back(
			ClientVersion(
			lastProfile++, 
			clientName, 
			lastVersion, 
			currentVersion, 
			comment, 
			address, 
			clientAddress, 
			updateTime,
			alert,
			updated
			)
		);
		checkList.push_back(address);
		return clientVersions.back();
	}


	bool getClientVersion(int id, ClientVersion& cp) {
		Lock l(cs);
		for(ClientVersion::Iter i = clientVersions.begin(); i != clientVersions.end(); ++i) {
			if(i->getId() == id) {
				cp = *i;
				return true;
			}
		}
		return false;
	}

	void removeClientVersion(int id) {
		Lock l(cs);
		for(ClientVersion::Iter i = clientVersions.begin(); i != clientVersions.end(); ++i) {
			if(i->getId() == id) {
				clientVersions.erase(i);
				break;
			}
		}
	}

	void updateClientVersion(const ClientVersion& cp) {
		Lock l(cs);
		for(ClientVersion::Iter i = clientVersions.begin(); i != clientVersions.end(); ++i) {
			if(i->getId() == cp.getId()) {
				*i = cp;
				break;
			}
		}
	}

	bool moveClientVersion(int id, int pos/*, int position*/) {
		dcassert(pos == -1 || pos == 1);
		Lock l(cs);
		for(ClientVersion::Iter i = clientVersions.begin(); i != clientVersions.end(); ++i) {
			if(i->getId() == id) {
				swap(*i, *(i + pos));
				return true;
			}
		}
		return false;
	}

	void checkClient(const string& aAddress){
		fire(VersionManagerListener::MAKE_NEW_CONNECTION, aAddress);
	}

	void loadClientList();
	void saveClientList();


private:
	void loadClientList(SimpleXML* aXml);
	bool downloadFile(const string& aFile){
		if(!downloadActive){
			downloadActive = true;
			c.addListener(this);
			c.downloadFile(aFile);
			return true;
		}
		return false;
	}

	CriticalSection cs;
	friend class Singleton<ClientVersionManager>;
	
	//Constructor
	ClientVersionManager() : minutes(0), downloadActive(false) {
		TimerManager::getInstance()->addListener(this);
		addListener(this);
	}

	//Detstructor
	virtual ~ClientVersionManager() {
		TimerManager::getInstance()->removeListener(this);
		removeListener(this);
	}

	//TimerManagerListnener
	virtual void on(TimerManagerListener::Minute, u_int32_t aTick) throw();	

	// HttpConnectionListener
	virtual void on(HttpConnectionListener::Data, HttpConnection* /*conn*/, const u_int8_t*, int) throw();
	virtual void on(HttpConnectionListener::Complete, HttpConnection* /*conn*/, const string&) throw();
	virtual void on(HttpConnectionListener::Failed, HttpConnection* /*conn*/, const string&) throw();

	//VersionManagerListener
	virtual void on(VersionManagerListener::Types type, const string& aAddy) throw();
	
	HttpConnection c;
	ClientVersion::List clientVersions;

	int minutes;
	int lastProfile;

	string downBuf;

	StringList checkList;
	bool downloadActive;


	
};
#endif // !defined(__CLIENT_VERSION_MANAGER_H)
/**
 * @file
 * $Id: ClientVersionManager.h 330 2005-09-01 17:52:15Z Pothead $
 */